package com.zyj.core.builder;

import com.zyj.core.sqlnode.*;
import com.zyj.core.sqlsource.DynamicSqlSource;
import com.zyj.core.sqlsource.RawSqlSource;
import com.zyj.core.sqlsource.SqlSource;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;

import java.util.ArrayList;
import java.util.List;

public class XMLScriptBuilder {
    private boolean isDynamic = false;

    /**
     * <select id="queryUserByParams2"
     * 		resultType="com.zyj.mybatis.po.User"
     * 		statementType="prepared">
     * 		SELECT * FROM user WHERE sex = #{sex}
     * 	</select>
     */

    /**
     * 根据select标签解析sql得到SqlSource对象
     *
     * @param selectElement
     * @return
     */
    public SqlSource parseScriptNode(Element selectElement) {
        // 传入select标签
        // 1、解析动态标签，获取SqlNode信息
        SqlNode mixedSqlNode = parseDynamicTags(selectElement);
        // 2、封装SqlSource
        SqlSource sqlSource = null;

        /**
         * 根据isDynamic标记来判断当前sql是否是动态sql，即是否包含动态标签或者${}
         *
         * 传入的mixedSqlNode是已经根据配置文件中的标签解析完成，封装好的SqlNode对象
         */
        if (isDynamic) {
            // 如果当前sql包含动态标签或者${}
            // 此时还没有完成sql解析，仅仅只是得到了DynamicSqlSource对象
            sqlSource = new DynamicSqlSource(mixedSqlNode);
        } else {
            // 如果当前sql不包含动态标签以及${}
            // 在这种情况下，得到sqlNode之后，在创建RawSqlSource时就已经同时完成了解析sql的工作
            // 此时已经将 #{} 通过字符串处理替换成了 "?"
            // SELECT * FROM user WHERE sex = ?
            // 此时已经完成了sql解析，得到了可以执行的sql了，并且也完成了参数映射的封装，得到了参数映射
            sqlSource = new RawSqlSource(mixedSqlNode);
        }
        return sqlSource;
    }

    private SqlNode parseDynamicTags(Element selectElement) {
        List<SqlNode> sqlNodes = new ArrayList<>();

        // 得到sql标签中的片段数量
        int nodeCount = selectElement.nodeCount();

        // 遍历select标签中的所有node，即每一个sql片段就是一个node
        for (int i = 0; i < nodeCount; i++) {
            Node node = selectElement.node(i);
            if (node instanceof Text) {
                // 如果当前片段不包含动态标签
                String text = node.getText().trim();
                if (text.equals("")) {
                    continue;
                }
                TextSqlNode textSqlNode = new TextSqlNode(text);
                if (textSqlNode.isDynamic()) {
                    // 如果当前片段包含 ${}
                    isDynamic = true;
                    sqlNodes.add(textSqlNode);
                } else {
                    // 如果当前片段不包含 ${}
                    sqlNodes.add(new StaticTextSqlNode(text));
                }

            } else if (node instanceof Element) {
                // 此处就是动态标签的处理逻辑
                isDynamic = true;

                Element element = (Element) node;
                String name = element.getName();
                // TODO 使用策略模式进行优化
                if ("if".equals(name)) {
                    String test = element.attributeValue("test");
                    SqlNode mixedSqlNode = parseDynamicTags(element);

                    SqlNode ifSqlNode = new IfSqlNode(test, mixedSqlNode);

                    sqlNodes.add(ifSqlNode);
                } else if ("where".equals(name)) {

                }
            } else {
                //...
            }
        }

        return new MixedSqlNode(sqlNodes);
    }

}
